package com.feather.tenia.oracle.saver;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;

import oracle.jdbc.OracleTypes;
import oracle.jdbc.driver.OracleConnection;
import oracle.sql.BLOB;

import com.feather.common.data.Column;
import com.feather.common.db.DbSaver;
import com.feather.common.util.RuntimeError;

/**
 * @author flogyin
 */
public class String_BLOB implements DbSaver {
	@Override
	@SuppressWarnings("rawtypes")
	public Class getJavaType() {
		return String.class;
	}

	@Override
	public String getDbType() {
		return "blob";
	}

	@Override
	public int getSqlType() {
		return OracleTypes.BLOB;
	}

	@Override
	public boolean matchNull() {
		return false;
	}

	@Override
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public boolean save(Object value, PreparedStatement statement, Column column) throws SQLException {
		Connection connection = statement.getConnection();
		if (connection instanceof OracleConnection) {
			forOracleConnection(value, statement, column);
		} else {
			if (value != null) {
				String str = (String) value;
				String encoding = "UTF-8";
				byte[] bytes = null;
				try {
					bytes = str.getBytes(encoding);
				} catch (UnsupportedEncodingException ex) {
					HashMap params = new HashMap();
					params.put("String", str);
					params.put("Charset", encoding);
					throw RuntimeError.create(ex, str, "getBytes", params);
				}
				ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
				statement.setBinaryStream(column.getOrdinal(), bais, bytes.length);
			} else {
				statement.setBlob(column.getOrdinal(), BLOB.empty_lob());
			}
		}
		return true;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private void forOracleConnection(Object value, PreparedStatement statement, Column column) throws SQLException {
		BLOB blob = null;
		if (value != null) {
			String str = (String) value;
			byte[] bytes = null;
			String encoding = "UTF-8";
			try {
				bytes = str.getBytes(encoding);
			} catch (UnsupportedEncodingException ex) {
				HashMap params = new HashMap();
				params.put("String", str);
				params.put("charset", encoding);
				throw RuntimeError.create(ex, str, "getBytes", params);
			}

			OutputStream os = null;
			blob = BLOB.createTemporary(statement.getConnection(), false, BLOB.DURATION_SESSION);
			try {
				os = blob.getBinaryOutputStream();
				os.write(bytes, 0, bytes.length);
			} catch (IOException ex) {
				throw new SQLException(ex.getMessage());
			} finally {
				if (os != null) {
					try {
						os.close();
					} catch (IOException ex) {
						ex.printStackTrace();
					}
				}
			}
		} else {
			blob = BLOB.empty_lob();
		}
		statement.setBlob(column.getOrdinal(), blob);
	}
}
